#ifndef _TREE_H
#define _TREE_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


typedef struct
{
    char type;
    union
    {
        char op;
        int number;
    };
} info;


typedef info data_t;

struct pretree;

typedef struct pretree tree;

struct pretree
{
    data_t data;
    tree* left;
    tree* right;
};

tree* tree_ctor();
int tree_dtor(tree* Tree);
int tree_ok(tree* Tree);
int tree_dump(tree* Tree, FILE* output);
int tree_filedump(tree* Tree, const char* FileName);
tree* new_node();
int add_node(tree* here, tree* this, char lor);
tree* MakeTree(const char* TextTree);
tree* MakeNode(FILE* source);


tree* tree_ctor(data_t data)
{
    tree* result = (tree*) calloc(1, sizeof(tree));
    result -> data = data;
    return result;
}

int tree_dtor(tree* Tree)
{
    if (!tree_ok(Tree)) return 0;
    if (Tree -> left)  tree_dtor(Tree -> left);
    if (Tree -> right) tree_dtor(Tree -> right);
    free(Tree);
    return 1;
}

int tree_ok(tree* Tree)
{
    if (!Tree) return 0;
    if (Tree -> right && Tree -> left) return tree_ok(Tree -> left)*tree_ok(Tree -> right);
    if (Tree -> right) return tree_ok(Tree -> right);
    if (Tree -> left) return tree_ok(Tree -> left);
    return 1;
}

int tree_dump(tree* Tree, FILE* output)
{
    if(!tree_ok(Tree)) return 0;

    if (Tree -> left) tree_dump(Tree -> left, output);
    if (Tree -> data.type == 'n') fprintf(output, "(%d", Tree -> data.number);
    else fprintf(output, "(%c", Tree -> data.op);
    if (Tree -> right) tree_dump(Tree -> right, output);
    fprintf(output, "%c", ')');
    return 1;
}

int tree_filedump(tree* Tree, const char* FileName)
{
    if (!tree_ok(Tree)) return 0;
    FILE* dump = fopen(FileName, "w");
    if (!dump) return 0;
    int success = tree_dump(Tree, dump);
    fclose(dump);
    return success;
}

tree* new_node(data_t data)
{
    tree* result = (tree*) calloc(1, sizeof(tree));
    result -> data = data;
    return result;
}

int add_node(tree* here, tree* this, char lor)
{
    if(!tree_ok(here) || !tree_ok(this)) return 0;
    if (lor == 'l')
    {
        if (here -> left) return 0;
        here -> left  = this;
        return 1;
    }
    if (lor = 'r')
    {
        if (here -> right) return 0;
        here -> right = this;
        return 1;
    }
    return 0;
}


#endif // _TREE_H
